﻿using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace WorldMapWebPart {

    public enum MapType { GoogleMap, VirtualEarth }

    [XmlRoot(Namespace = "http://webpart-shop.com/WebPart/v1/MediaPlayerWebpart")]
    public class WorldMapWebPart : WebPart {
        private string mapCenter;
        private string geoLocations;
        private string googleApiKey;
        private MapType mapType;

        [WebPartStorage(Storage.Shared),
        FriendlyName("The type of the map"),
        Category("Map"),
        Browsable(true)]
        public MapType MapType {
            get {
                return mapType;
            }
            set {
                mapType = value;
            }
        }

        [WebPartStorage(Storage.Shared),
        FriendlyName("The center of the map"),
        Category("Map"),
        Browsable(true)]
        public string MapCenter {
            get {
                return mapCenter;
            }
            set {
                mapCenter = value;
            }
        }

        [WebPartStorage(Storage.Shared),
        FriendlyName("Locations on the map"),
        Category("Map"),
        Browsable(true)]
        public string GeoLocations {
            get {
                return geoLocations;
            }
            set {
                geoLocations = value;
            }
        }

        [WebPartStorage(Storage.Shared),
        FriendlyName("Google API Key"),
        Category("Map"),
        Browsable(true)]
        public string GoogleApiKey {
            get {
                return googleApiKey;
            }
            set {
                googleApiKey = value;
            }
        }

        [System.Web.UI.WebControls.WebParts.ConnectionConsumer("GeoLocations")]
        public void SetGeoLocations(System.Web.UI.WebControls.WebParts.IWebPartField field) {
            field.GetFieldValue(new System.Web.UI.WebControls.WebParts.FieldCallback(delegate(object value) {
                geoLocations = Convert.ToString(value);
                CreateChildControls();
            }));
        }

        protected override void CreateChildControls() {
            try {
                Controls.Clear();
                string[] geoLocationLines;
                if (!string.IsNullOrEmpty(geoLocations)) {
                    geoLocationLines = geoLocations.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                } else {
                    geoLocationLines = new string[] { };
                }
                switch (mapType) {
                    case MapType.GoogleMap:
                        HtmlGenericControl cnt = new HtmlGenericControl();
                        string locationsScript = string.Empty;
                        foreach (string loc in geoLocationLines) {
                            locationsScript += "geocoder.getLocations('" + loc.Replace("'", "\\'") + "', addAddressToMap);\r\n";
                        }
                        cnt.InnerHtml = string.Format(
@"<script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key={0}'
      type='text/javascript'></script>
    <script type='text/javascript'>

    //<![CDATA[
    var map;
    var geocoder;
    function load() {{
      if (GBrowserIsCompatible()) {{
        map = new GMap2(document.getElementById('map{5}'), {{ size: new GSize({6},{7}) }});
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());
        geocoder = new GClientGeocoder();
      }}
    }}
    function addAddressToMap(response) {{
      if (!response || response.Status.code != 200) {{
        alert('Sorry, we were unable to geocode that address');
      }} else {{
        var place = response.Placemark[0];
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
        var marker = new GMarker(point);
        GEvent.addListener(marker, 'click', function() {{
          marker.openInfoWindowHtml('<b>' + place.address + '</b>');
        }});
        map.addOverlay(marker);
        return marker;
      }}
    }}
    function centerMap(response) {{
      if (!response || response.Status.code != 200) {{
        alert('Sorry, we were unable to geocode that address');
      }} else {{
        place = response.Placemark[0];
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
        map.setCenter(point,13);
      }}
    }}
    //]]>
    </script>
    <div id='map{5}' style='width: {1}; height: {2}'></div>
<script type='text/javascript'>
    load();
    geocoder.getLocations('{3}', centerMap);
    {4}
</script>", googleApiKey, string.IsNullOrEmpty(Width) ? "320px" : Width, string.IsNullOrEmpty(Height) ? "240px" : Height,
                  string.IsNullOrEmpty(mapCenter) ? string.Empty : mapCenter.Replace("'", "\\'"), locationsScript, Qualifier,
                  string.IsNullOrEmpty(Width) ? "320" : Width.Replace("px", ""), string.IsNullOrEmpty(Height) ? "240" : Height.Replace("px", ""));
                        Controls.Add(cnt);
                        break;
                    case MapType.VirtualEarth:
                        HtmlGenericControl cnt2 = new HtmlGenericControl();
                        string locationsString2 = string.Empty;
                        foreach (string loc in geoLocationLines) {
                            locationsString2 += "FindLoc('" + loc + "');\r\n";
                        }
                        cnt2.InnerHtml = string.Format(
@"<script type='text/javascript' src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script>
<script type='text/javascript'>
var map = null;
var results = null;
function GetMap()
{{
    try {{
        map = new VEMap('map{2}');
        map.LoadMap(null, 13);
        results = map.Find(null,
            '{4}',
            null,
            null,
            0,
            1,
            true,
            true,
            true,
            true,
            CenterMapCallback);
    }} catch (e) {{
        alert(e.message);
    }}
}}
function FindLoc(where)
{{
    try
    {{
        results = map.Find(null,
            where,
            null,
            null,
            0,
            1,
            true,
            true,
            true,
            true,
            MoreResults);
    }}
    catch(e)
    {{
        alert(e.message);
    }}
}}
function CenterMapCallback(layer, resultsArray, places, hasMore, veErrorMessage) {{
    if (places != null && places.length > 0) {{
        map.SetCenter(places[0].LatLong);
    }}
    {3}
}}
function MoreResults(layer, resultsArray, places, hasMore, veErrorMessage)
{{
    if (places != null && places.length > 0) {{
        var shape = new VEShape(VEShapeType.Pushpin, places[0].LatLong);
        shape.SetTitle(places[0].Name);
        map.AddShape(shape);
    }}
}}
</script>
<div id='map{2}' style='width: {0}; height: {1}; position: relative'></div>
<script type='text/javascript'>
var oldHandler = window.onload;
if (typeof(oldHandler) != 'function') {{
    window.onload = function() {{
        GetMap();
    }}
}} else {{
    window.onload = function() {{
        if (oldHandler) {{
            oldHandler();
        }}
        GetMap();
    }}
}}
</script>",
                            string.IsNullOrEmpty(Width) ? "320px" : Width, string.IsNullOrEmpty(Height) ? "240px" : Height, Qualifier,
                            locationsString2, mapCenter.Replace("'", "\\'"));
                        Controls.Add(cnt2);
                        break;
                }
            } catch (Exception ex) {
                HtmlGenericControl cnt = new HtmlGenericControl();
                cnt.InnerText = ex.ToString();
                Controls.Add(cnt);
            }
        }
    }
}
